package main

import (
	"flag"
	"fmt"
	"net"
	"os/exec"
	"strings"
	"time"

	example "git.oschina.net/wkc/master-key-go/proto/example"
	"github.com/go-vgo/robotgo"
	"github.com/gorilla/websocket"
	"github.com/mgutz/logxi/v1"
	"github.com/parnurzeal/gorequest"
	"github.com/pborman/uuid"
	"github.com/pkg/errors"
)

func main() {
	if !log.IsInfo() {
		log.DefaultLog.SetLevel(log.LevelInfo)
	}
	var (
		id          = ""
		server      = ""
		Version     = "20170326-dev-2"
		openBrowser = false
	)

	{
		flag.StringVar(&id, "id", "", "身份识别ID")
		flag.StringVar(&server, "server", "https://master-key.hi-hi.cn", "服务器地址")
		flag.BoolVar(&openBrowser, "open_browser", true, "自动打开浏览器")
		flag.Parse()
		if id == "" {
			id = uuid.New()[:6]
		}
	}

	{
		var ver example.VersionResponse
		_, _, err := gorequest.New().Get(fmt.Sprintf("%s/v1/version?version=%s", server, Version)).EndStruct(&ver)
		if err != nil {
			log.Error("get version", "err", fmt.Sprintf("%+v", err))
		}
		if ver.Message != "" {
			log.Warn(ver.Message)
		}
	}

	{
		if openBrowser {
			exec.Command("open", fmt.Sprintf("https://master-key.hi-hi.cn/control.html?from=cmd&version=%s&id=%s", Version, id)).Run()
		}
	}

	for {
		err := func() error {
			log.Info("master-key-agent aganet run", "id", id, "version", Version)
			wsHost := strings.NewReplacer("http://", "ws://", "https://", "wss://").Replace(server)

			conn, _, err := websocket.DefaultDialer.Dial(wsHost+"/v1/listen", nil)
			if err != nil {
				return errors.Wrap(err, "dial server")
			}
			defer conn.Close()
			err = conn.WriteJSON(&example.ListenRequest{Id: id})
			if err != nil {
				return errors.Wrap(err, "send resp")
			}
			for {
				var resp example.ListenResponse
				conn.SetReadDeadline(time.Now().Add(time.Second * 15))
				err = conn.ReadJSON(&resp)
				if err != nil {
					if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
						return nil
					}
					return errors.Wrap(err, "read resp")
				}
				log.Debug("resp", resp)
				if resp.Op == nil {
					return errors.New("empty resp")
				}
				switch resp.Op.Type {
				case "KeyTap":
					if resp.Op.Modifier == nil {
						robotgo.KeyTap(resp.Op.Key)
					} else {
						robotgo.KeyTap(resp.Op.Key, resp.Op.Modifier)
					}
				case "TypeString":
					robotgo.TypeString(resp.Op.Key)
				}
			}
		}()
		if err != nil {
			log.Error("run", "err", fmt.Sprintf("%+v", err))
		}
		time.Sleep(time.Second)
	}
}
